package com.googlecode.icecube.presentation;


import java.util.Enumeration;

import javax.faces.event.ActionEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import org.springframework.beans.factory.annotation.Autowired;

import com.googlecode.icefusion.ui.commons.BackingBeanForm;
import com.googlecode.icefusion.ui.commons.constant.ICEfusionConsts;
import com.googlecode.icefusion.ui.commons.constant.Context;


/**
 * Manages tree examples.
 * 
 * @author Rainer Eschen
 * 
 */
public class Tree extends BackingBeanForm {

    private static final long serialVersionUID = 4811237804822322601L;

    @Autowired
    private ICEfusionConsts consts;

    @Autowired
    private Context context;

    /**
     * Tree model to show.
     */
    private DefaultTreeModel model;

    /**
     * Last clicked node.
     */
    private TreeNodeUserObject selectedUserObject;

    public void init() {

        int ids = 0;
        String skin = consts.getSkinBase() + "/" + context.getSkin();
        // create root node with its children expanded
        DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode();
        TreeNodeUserObject rootObject = new TreeNodeUserObject(rootTreeNode, skin);
        rootObject.setId(ids++);
        rootObject.setText("Root Node");
        rootTreeNode.setUserObject(rootObject);

        model = new DefaultTreeModel(rootTreeNode);

        // add some child nodes
        for (int i = 0; i < 3; i++) {
            DefaultMutableTreeNode branchNode = new DefaultMutableTreeNode();
            TreeNodeUserObject branchObject = new TreeNodeUserObject(branchNode, skin);
            branchObject.setId(ids++);
            branchObject.setText("node-" + i);
            branchObject.setLeaf(false);
            branchNode.setUserObject(branchObject);
            rootTreeNode.add(branchNode);

            // add some more sub children
            for (int k = 0; k < 2; k++) {
                DefaultMutableTreeNode subBranchNode = new DefaultMutableTreeNode();
                TreeNodeUserObject subBranchObject = new TreeNodeUserObject(subBranchNode, skin);
                subBranchObject.setId(ids++);
                subBranchObject.setText("sub-node-" + i + "-" + k);
                subBranchObject.setLeaf(true);
                subBranchNode.setUserObject(subBranchObject);
                branchNode.add(subBranchNode);
            }
        }
    }

    /**
     * Event processing for a clicked node. Identification is done via the UserObject id that is transported via the
     * Request parameters.
     * 
     * @param event event parameters
     */
    public void nodeSelected(ActionEvent event) {

        String nodeId = consts.getRequestParameter("nodeId");
        this.setSelectedUserObject(this.findUserObject(nodeId));
    }

    /**
     * Search for the node that was clicked.
     * 
     * @param nodeId id of the user object of the node
     * @return user object
     */
    private TreeNodeUserObject findUserObject(String nodeId) {
        DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode)model.getRoot();
        DefaultMutableTreeNode node;
        TreeNodeUserObject userObject;
        Enumeration nodes = rootNode.depthFirstEnumeration();
        while (nodes.hasMoreElements()) {
            node = (DefaultMutableTreeNode)nodes.nextElement();
            userObject = (TreeNodeUserObject)node.getUserObject();
            if (nodeId.equals(String.valueOf(userObject.getId()))) {
                return userObject;
            }
        }
        return null;
    }

    public TreeNodeUserObject getSelectedUserObject() {
        return selectedUserObject;
    }

    public void setSelectedUserObject(TreeNodeUserObject selectedUserObject) {
        this.selectedUserObject = selectedUserObject;
    }

    public void setModel(DefaultTreeModel model) {
        this.model = model;
    }

    public DefaultTreeModel getModel() {
        init();
        return model;
    }
}
